package cn.caidabao.gb.component.sip;

import cn.caidabao.gb.bean.*;
import cn.caidabao.gb.component.sip.server.request.recieve.DefaultMessageRequestHandler;
import cn.caidabao.gb.component.sip.server.request.recieve.DefaultRegisterHandler;
import cn.caidabao.gb.component.sip.server.response.recieve.InfoMessageResponseHandler;
import cn.caidabao.gb.component.sip.server.response.recieve.ReceiveInviteMessageResponseHandler;
import cn.caidabao.gb.config.GbServerConfig;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sdp.SdpFactory;
import javax.sdp.SdpParseException;
import javax.sdp.SessionDescription;
import javax.sip.*;
import javax.sip.address.Address;
import javax.sip.address.AddressFactory;
import javax.sip.address.SipURI;
import javax.sip.header.*;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Properties;
import java.util.UUID;

@Slf4j
@Component
public class CustomSipServer implements SipListener {

    public static CustomSipServer server;

    static SipStack sipStack;
    public static MessageFactory messageFactory;

    static AddressFactory addressFactory;

    static HeaderFactory headerFactory;

    public SipProvider udpSipProvider;
    private SipProvider tcpSipProvider;
    
    @Resource
    private GbServerConfig gbServerConfig;
    @Resource
    private ReceiveInviteMessageResponseHandler inviteMessageResponseHandler;
    @Resource
    private DefaultMessageRequestHandler defaultMessageRequestHandler;
    @Resource
    private InfoMessageResponseHandler infoMessageResponseHandler;

    public void init() throws Exception {
        Properties props = new Properties();
        props.setProperty("javax.sip.IP_ADDRESS", gbServerConfig.getIp());
        props.setProperty("javax.sip.STACK_NAME", "OGS");
        SipFactory factory = SipFactory.getInstance();
        System.out.println(factory.getPathName()+"--------------------------------------");
        sipStack = factory.createSipStack(props);
        messageFactory = factory.createMessageFactory();
        ListeningPoint lp = sipStack.createListeningPoint(gbServerConfig.getIp(), gbServerConfig.getPort(), "udp");
        udpSipProvider = sipStack.createSipProvider(lp);
        udpSipProvider.addSipListener(this);
//        ListeningPoint lp1 = sipStack.createListeningPoint(gbServerConfig.getIp(), gbServerConfig.getPort(), "tcp");
//        tcpSipProvider = sipStack.createSipProvider(lp1);
//        tcpSipProvider.addSipListener(this);
        addressFactory = factory.createAddressFactory();
        headerFactory = factory.createHeaderFactory();
        server = this;
    }

    @Override
    public void processRequest(RequestEvent reqEvent) {
        // 处理请求（如注册、呼叫）
        ViaHeader viaHeader = (ViaHeader)reqEvent.getRequest().getHeader(ViaHeader.NAME);
        String transport = viaHeader.getTransport().toLowerCase();
        final SipProvider sipProvider = transport.equals("tcp")?tcpSipProvider:transport.equals("udp")?udpSipProvider:null;
        if (sipProvider==null)throw new RuntimeException("transport is not supported");
        if (reqEvent.getRequest().getMethod().equals(Request.REGISTER)) {
            new DefaultRegisterHandler().handleRequest(reqEvent,new GBSipContext(sipProvider,transport));
        }else if (reqEvent.getRequest().getMethod().equals(Request.MESSAGE)){
            defaultMessageRequestHandler.handleRequest(reqEvent,new GBSipContext(sipProvider,transport));
        }else {
            log.info("收到未知的请求：{}",reqEvent.getRequest().getMethod());
        }
    }

    @SneakyThrows
    @Override
    public void processResponse(ResponseEvent responseEvent) {
        Response response = responseEvent.getResponse();
        CSeqHeader cSeqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);
        if(response.getStatusCode()==100){
            return;
        }
        if (cSeqHeader.getMethod().equals(Request.INVITE)){
            inviteMessageResponseHandler.handleResponse(responseEvent);
        }else if (cSeqHeader.getMethod().equals(Request.MESSAGE)&&response.getStatusCode()==200){
            System.out.println("收到message 200 OK");
        }else if (cSeqHeader.getMethod().equals(Request.MESSAGE)){
            String content = new String((byte[]) response.getContent());
            System.out.println("收到message内容："+content);
        } else if (cSeqHeader.getMethod().equals(Request.INFO)) {
            infoMessageResponseHandler.handleResponse(responseEvent);
        } else {
            log.info("收到未知的响应:{}",cSeqHeader.getMethod());
        }

    }

    public static Gb28181Sdp parseSDP(String sdpStr) throws SdpParseException {

        // jainSip不支持y= f=字段， 移除以解析。
        int ssrcIndex = sdpStr.indexOf("y=");
        int mediaDescriptionIndex = sdpStr.indexOf("f=");
        // 检查是否有y字段
        SessionDescription sdp;
        String ssrc = null;
        String mediaDescription = null;
        if (mediaDescriptionIndex == 0 && ssrcIndex == 0) {
            sdp = SdpFactory.getInstance().createSessionDescription(sdpStr);
        }else {
            String lines[] = sdpStr.split("\\r?\\n");
            StringBuilder sdpBuffer = new StringBuilder();
            for (String line : lines) {
                if (line.trim().startsWith("y=")) {
                    ssrc = line.substring(2);
                }else if (line.trim().startsWith("f=")) {
                    mediaDescription = line.substring(2);
                }else {
                    sdpBuffer.append(line.trim()).append("\r\n");
                }
            }
            sdp = SdpFactory.getInstance().createSessionDescription(sdpBuffer.toString());
        }
        return Gb28181Sdp.getInstance(sdp, ssrc, mediaDescription);
    }

    @Override
    public void processTimeout(TimeoutEvent timeoutEvent) {

    }

    @Override
    public void processIOException(IOExceptionEvent ioExceptionEvent) {

    }

    @Override
    public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {

    }

    @Override
    public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {

    }

    public CallMessage sendInviteMessage(String deviceId, String channelId, String deviceIp, String mediaServerIp, int mediaServerPort, String requestName,String sdp) throws InvalidArgumentException, ParseException, SipException {
        String localIp = gbServerConfig.getIp();
        int localPort = gbServerConfig.getPort();
        String sipServerId = gbServerConfig.getServerId();
        Address fromAddress = addressFactory.createAddress("sip:"+sipServerId+"@" + localIp);
        FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, UUID.randomUUID().toString().replace("-",""));
        Address toAddress = addressFactory.createAddress("sip:" + deviceId + "@" + deviceIp);
        ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, UUID.randomUUID().toString().replace("-",""));
        // 创建请求URI
        SipURI requestURI = addressFactory.createSipURI(deviceId, deviceIp);

        // 创建Call-ID
        CallIdHeader callId = udpSipProvider.getNewCallId();

        // 创建Via头部
        ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
        ViaHeader viaHeader = headerFactory.createViaHeader(localIp, localPort, "udp", null);
        viaHeaders.add(viaHeader);

        // 创建CSeq头部
        CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(1L, requestName);

        // 创建Max-Forwards头部
        MaxForwardsHeader maxForwards = headerFactory.createMaxForwardsHeader(70);

        // 创建Contact头部
        SipURI contactURI = addressFactory.createSipURI(sipServerId, localIp);
        contactURI.setPort(localPort);
        Address contactAddress = addressFactory.createAddress(contactURI);
        ContactHeader contactHeader = headerFactory.createContactHeader(contactAddress);

        // 创建Subject头部(GB28181特有)
        SubjectHeader subjectHeader = headerFactory.createSubjectHeader(deviceId + ":0,"+sipServerId+":0");

        // 创建INVITE请求
        Request inviteRequest = messageFactory.createRequest(
                requestURI,
                requestName,
                callId,
                cSeqHeader,
                fromHeader,
                toHeader,
                viaHeaders,
                maxForwards
        );

        // 添加头部
        inviteRequest.addHeader(contactHeader);
        inviteRequest.addHeader(subjectHeader);

        // 设置SDP内容
        ContentTypeHeader contentTypeHeader = headerFactory.createContentTypeHeader("application", "sdp");
        inviteRequest.setContent(sdp, contentTypeHeader);

        // 发送请求
        ClientTransaction clientTransaction = udpSipProvider.getNewClientTransaction(inviteRequest);
        clientTransaction.sendRequest();
        return new CallMessage(callId.getCallId(),((CSeqHeader)inviteRequest.getHeader(CSeqHeader.NAME)).getSeqNumber());
    }

    @SneakyThrows
    public void sendByeMessage(String deviceId, String channelId, String deviceIp, String callId,Long cSeq){
        String localIp = gbServerConfig.getIp();
        int localPort = gbServerConfig.getPort();
        String sipServerId = gbServerConfig.getServerId();
        Address fromAddress = addressFactory.createAddress("sip:"+sipServerId+"@" + localIp);
        FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, UUID.randomUUID().toString().replace("-",""));
        Address toAddress = addressFactory.createAddress("sip:" + deviceId + "@" + deviceIp);
        ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, UUID.randomUUID().toString().replace("-",""));
        // 创建请求URI
        SipURI requestURI = addressFactory.createSipURI(deviceId, deviceIp);


        // 创建Via头部
        ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
        ViaHeader viaHeader = headerFactory.createViaHeader(localIp, localPort, "udp", null);
        viaHeaders.add(viaHeader);

        // 创建CSeq头部
        CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(cSeq, Request.BYE);

        CallIdHeader callIdHeader = headerFactory.createCallIdHeader(callId);

        // 创建Max-Forwards头部
        MaxForwardsHeader maxForwards = headerFactory.createMaxForwardsHeader(70);

        // 创建Contact头部
        SipURI contactURI = addressFactory.createSipURI(sipServerId, localIp);
        contactURI.setPort(localPort);
        Address contactAddress = addressFactory.createAddress(contactURI);
        ContactHeader contactHeader = headerFactory.createContactHeader(contactAddress);
        // 创建Subject头部(GB28181特有)
        SubjectHeader subjectHeader = headerFactory.createSubjectHeader(deviceId + ":0,"+sipServerId+":0");
        // 创建INVITE请求
        Request inviteRequest = messageFactory.createRequest(
                requestURI,
                Request.BYE,
                callIdHeader,
                cSeqHeader,
                fromHeader,
                toHeader,
                viaHeaders,
                maxForwards
        );

        // 添加头部
        inviteRequest.addHeader(contactHeader);
        inviteRequest.addHeader(subjectHeader);
        // 发送请求
        ClientTransaction clientTransaction = udpSipProvider.getNewClientTransaction(inviteRequest);
        clientTransaction.sendRequest();
    }


    private String createSdpContent(String mediaIp, int mediaPort,String channelId) {
        return "v=0\r\n" +
                "o=" + channelId + " 0 0 IN IP4 " + mediaIp + "\r\n" +
                "s=Play\r\n" +
                "c=IN IP4 " + mediaIp + "\r\n" +
                "t=0 0\r\n" +
                "m=video " + mediaPort + " RTP/AVP 96\r\n" +
                "a=recvonly\r\n" +
                "a=rtpmap:96 PS/90000\r\n";
    }

    @SneakyThrows
    public String sendMessage(GBSipRegisterSession gbSipRegisterSession, QueryObject extraData) {
        String localIp = gbServerConfig.getIp();
        int localPort = gbServerConfig.getPort();
        String sipServerId = gbServerConfig.getServerId();
        Address fromAddress = addressFactory.createAddress("sip:"+sipServerId+"@" + localIp);
        FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, UUID.randomUUID().toString().replace("-",""));
        String deviceId = gbSipRegisterSession.getDeviceId();
        String deviceIp = gbSipRegisterSession.getIp()+":"+gbSipRegisterSession.getPort();
        Address toAddress = addressFactory.createAddress("sip:" + deviceId + "@" + deviceIp);
        ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, UUID.randomUUID().toString().replace("-",""));
        // 创建请求URI
        SipURI requestURI = addressFactory.createSipURI(deviceId, deviceIp);


        // 创建Via头部
        ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
        ViaHeader viaHeader = headerFactory.createViaHeader(localIp, localPort, "udp", null);
        viaHeaders.add(viaHeader);
        CallIdHeader callIdHeader = udpSipProvider.getNewCallId();
        // 创建CSeq头部
        CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(1L, Request.MESSAGE);


        // 创建Max-Forwards头部
        MaxForwardsHeader maxForwards = headerFactory.createMaxForwardsHeader(70);

        // 创建Contact头部
        SipURI contactURI = addressFactory.createSipURI(sipServerId, localIp);
        contactURI.setPort(localPort);
        Address contactAddress = addressFactory.createAddress(contactURI);
        ContactHeader contactHeader = headerFactory.createContactHeader(contactAddress);
        // 创建Subject头部(GB28181特有)
        SubjectHeader subjectHeader = headerFactory.createSubjectHeader(deviceId + ":0,"+sipServerId+":0");
        // 创建INVITE请求
        Request messageRequest = messageFactory.createRequest(
                requestURI,
                Request.MESSAGE,
                callIdHeader,
                cSeqHeader,
                fromHeader,
                toHeader,
                viaHeaders,
                maxForwards
        );

        // 添加头部
        messageRequest.addHeader(contactHeader);
        messageRequest.addHeader(subjectHeader);
        String content = extraData.getContent();
        messageRequest.setContent(content,headerFactory.createContentTypeHeader("Application","MANSCDP+xml"));
        messageRequest.addHeader(headerFactory.createContentLengthHeader(content.length()));
        // 发送请求
        ClientTransaction clientTransaction = udpSipProvider.getNewClientTransaction(messageRequest);
        clientTransaction.sendRequest();
        return callIdHeader.getCallId();
    }

    @SneakyThrows
    public String sendPlaybackCmd(String deviceId, String deviceIpPort, String cmdContent, Long callSeq,String callId) {
        String localIp = gbServerConfig.getIp();
        int localPort = gbServerConfig.getPort();
        String sipServerId = gbServerConfig.getServerId();
        Address fromAddress = addressFactory.createAddress("sip:"+sipServerId+"@" + localIp);
        FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, UUID.randomUUID().toString().replace("-",""));
        String deviceIp = deviceIpPort;
        Address toAddress = addressFactory.createAddress("sip:" + deviceId + "@" + deviceIp);
        ToHeader toHeader = SipFactory.getInstance().createHeaderFactory().createToHeader(toAddress, UUID.randomUUID().toString().replace("-",""));
        // 创建请求URI
        SipURI requestURI = addressFactory.createSipURI(deviceId, deviceIp);


        // 创建Via头部
        ArrayList<ViaHeader> viaHeaders = new ArrayList<>();
        ViaHeader viaHeader = headerFactory.createViaHeader(localIp, localPort, "udp", null);
        viaHeaders.add(viaHeader);
        CallIdHeader callIdHeader = headerFactory.createCallIdHeader(callId);
        // 创建CSeq头部
        CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(callSeq, Request.INFO);


        // 创建Max-Forwards头部
        MaxForwardsHeader maxForwards = headerFactory.createMaxForwardsHeader(70);

        // 创建Contact头部
        SipURI contactURI = addressFactory.createSipURI(sipServerId, localIp);
        contactURI.setPort(localPort);
        Address contactAddress = addressFactory.createAddress(contactURI);
        ContactHeader contactHeader = headerFactory.createContactHeader(contactAddress);
        // 创建Subject头部(GB28181特有)
        SubjectHeader subjectHeader = headerFactory.createSubjectHeader(deviceId + ":0,"+sipServerId+":0");
        // 创建INVITE请求
        Request messageRequest = messageFactory.createRequest(
                requestURI,
                Request.INFO,
                callIdHeader,
                cSeqHeader,
                fromHeader,
                toHeader,
                viaHeaders,
                maxForwards
        );

        // 添加头部
        messageRequest.addHeader(contactHeader);
        messageRequest.addHeader(subjectHeader);
        String content = cmdContent;
        messageRequest.setContent(content,headerFactory.createContentTypeHeader("Application","MANSRTSP"));
        messageRequest.addHeader(headerFactory.createContentLengthHeader(content.length()));
        // 发送请求
        ClientTransaction clientTransaction = udpSipProvider.getNewClientTransaction(messageRequest);
        clientTransaction.sendRequest();
        return callIdHeader.getCallId();
    }
}


